/*
 * Transfer.cpp
 *
 *  Created on: 2.4.2011
 *      Author: Tomas Srna
 */

#include "Transfer.h"

Transfer::Transfer(struct sockaddr_in client, IFile& fs,
		std::string fn, std::string m, std::ostream& logr)
	: filename(fn), mode(m), logger(logr), fs(fs), client(client) {

	remote_port = client.sin_port;

	srand(time(NULL)+rand());
	local_port = rand() % 65536 + 1024;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if(sock<0) throw "Error opening socket.";

	// Set to non-blocking
	if(0!=fcntl(sock, F_SETFL, O_NONBLOCK))
			throw "Error setting socket to non-blocking";

	// Bind
	bzero(&server, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(local_port);
	if(0 != bind(sock, (struct sockaddr*)&server, sizeof(server)))
		throw "Error binding socket to port";

	last_ack = 0;
	last_packet = 0;


}

Transfer::~Transfer() {
	close(sock);
}

void * Transfer::proc(Transfer* t)
{
	t->run();
	delete t;
	return NULL;
}

void Transfer::snd(const Packet& p)
{
	std::vector<char> v;
	p.store(v);
	sendto(sock, &v[0], v.size(),
			0, (struct sockaddr*)&client, sizeof(client));
}

std::ostream& operator << (std::ostream& os, const Transfer& tr)
{
	os << "[Transfer Type: " << tr.type();
	os << "; Filename: " << tr.filename;
	os << "; Local port: " << tr.local_port;
	os << "; Remote port: " << tr.remote_port;
	os << "; Last ACK: " << tr.last_ack;
	os << "]";
	return os;
}
